﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Automation;
using System.Windows.Forms;
using System.Xml.Linq;
using DevelopTool.Common;
using Sunny.UI;
using WindowTextExtractor.Diagnostics;
using WindowTextExtractor.Extensions;
using WindowTextExtractor.Native;
using WindowTextExtractor.Native.Structs;
using WindowTextExtractor.Utils;
using Application = System.Windows.Forms.Application;
using Image = System.Drawing.Image;

namespace WindowTextExtractor.Forms
{
    /// <summary>
    /// 窗口文本提取
    /// </summary>
    public partial class GetWindowTextForm : UIForm, IMessageFilter
    {
        private const string DEFAULT_FONT_NAME = "Courier New";
        private const int DEFAULT_FONT_SIZE = 10;
        private const int DEFAULT_FPS = 12;
        private const decimal DEFAULT_SCALE = 1;
        private readonly int _processId;
        private readonly int _messageId;
        private bool _isButtonTargetMouseDown;
        private string _64BitFilePath;
        private string _informationFileName;
        private string _textFileName;
        private string _textListFileName;
        private string _imageFileName;
        private string _environmentFileName;
        private IntPtr _windowHandle;
        private int _windowProcessId;
        private string _listText;
        private int _fps;
        private decimal _scale;
        private object _lockObject;
        private bool _refreshImage;
        private bool _imageTab;
        private bool _captureCursor;
        private Bitmap _image;

        private AccurateTimer _captureWindowTimer;
        private AccurateTimer _updatePictureBoxTimer;


        public GetWindowTextForm()
        {
            InitializeComponent();

            AppDomain.CurrentDomain.UnhandledException += OnCurrentDomainUnhandledException;
            Application.ThreadException += OnThreadException;

            _lockObject = new object();
            _isButtonTargetMouseDown = false;
            _processId = Process.GetCurrentProcess().Id;
            _messageId = User32.RegisterWindowMessage("WINDOW_TEXT_EXTRACTOR_HOOK");
            _64BitFilePath = string.Empty;
            _informationFileName = string.Empty;
            _textFileName = string.Empty;
            _textListFileName = string.Empty;
            _imageFileName = string.Empty;
            _environmentFileName = string.Empty;
            _windowHandle = IntPtr.Zero;
            _windowProcessId = 0;
            _listText = string.Empty;
            _refreshImage = false;
            _captureCursor = false;
            _imageTab = false;
            _fps = DEFAULT_FPS;
            _scale = DEFAULT_SCALE;
            _image = null;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            uiToolTip1.SetToolTip(this.btnTarget,"拖动获取窗口焦点");

            Application.AddMessageFilter(this);

            menuItemAlwaysOnTop_Click(this,EventArgs.Empty);
            OnContentChanged();

            var font = new Font(DEFAULT_FONT_NAME,DEFAULT_FONT_SIZE,FontStyle.Regular,GraphicsUnit.Point);
            if(font.Name == DEFAULT_FONT_NAME)
            {
                txtContent.Font = font;
                txtContent2.Font = font;
            }
            else
            {
                font.Dispose();
            }

            InitTimers(_fps);

            ThemHelper.SetSystemThem(this);

            UIMenuStyle uIMenuStyle = Setting.Theme.ControlThemColor;
            switch(uIMenuStyle)
            {
                case UIMenuStyle.Black:
                    pbContent.BackColor = ThemHelper.CustomBackColor_Black;
                    break;
                case UIMenuStyle.White:
                    pbContent.BackColor = ThemHelper.CustomBackColor_White;

                    break;
            }
        }


        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            Application.RemoveMessageFilter(this);
            _captureWindowTimer?.Stop();
            _updatePictureBoxTimer?.Stop();
        }

        protected override void WndProc(ref Message m)
        {
            switch(m.Msg)
            {
                case Constants.WM_COPYDATA:
                {
                    var cds = (CopyDataStruct)Marshal.PtrToStructure(m.LParam,typeof(CopyDataStruct));
                    var password = Marshal.PtrToStringAuto(cds.lpData);
                    txtContent.Text = password;
                    AddTextToList(password);
                    OnContentChanged();
                }
                break;
            }

            base.WndProc(ref m);
        }

        private void txtContent_TextChanged(object sender,EventArgs e) => OnContentChanged();


        private void menuItemSaveInformationAs_Click(object sender,EventArgs e)
        {
            var dialog = new SaveFileDialog
            {
                OverwritePrompt = true,
                ValidateNames = true,
                Title = "信息另存为",
                FileName = File.Exists(_informationFileName) ? Path.GetFileName(_informationFileName) : "文本.txt",
                DefaultExt = "txt",
                RestoreDirectory = false,
                Filter = "文本文件 (*.txt)|*.txt|All Files (*.*)|*.*"
            };

            if(!File.Exists(_informationFileName))
            {
                dialog.InitialDirectory = AssemblyUtils.AssemblyDirectory;
            }

            if(dialog.ShowDialog() != DialogResult.Cancel)
            {
                _informationFileName = dialog.FileName;
                var content = gvInformation.Tag != null ? ((WindowInformation)gvInformation.Tag).ToString() : string.Empty;
                File.WriteAllText(dialog.FileName,content,Encoding.UTF8);
            }
        }

        private void menuItemSaveTextAs_Click(object sender,EventArgs e)
        {
            var dialog = new SaveFileDialog
            {
                OverwritePrompt = true,
                ValidateNames = true,
                Title = "文本另存为",
                FileName = File.Exists(_textFileName) ? Path.GetFileName(_textFileName) : "文本.txt",
                DefaultExt = "txt",
                RestoreDirectory = false,
                Filter = "文本文件 (*.txt)|*.txt|All Files (*.*)|*.*"
            };

            if(!File.Exists(_textFileName))
            {
                dialog.InitialDirectory = AssemblyUtils.AssemblyDirectory;
            }

            if(dialog.ShowDialog() != DialogResult.Cancel)
            {
                _textFileName = dialog.FileName;
                File.WriteAllText(dialog.FileName,txtContent.Text,Encoding.UTF8);
            }
        }


        private void menuItemSaveTranslateTextAs_Click(object sender,EventArgs e)
        {
            var dialog = new SaveFileDialog
            {
                OverwritePrompt = true,
                ValidateNames = true,
                Title = "翻译文本另存为",
                FileName = File.Exists(_textFileName) ? Path.GetFileName(_textFileName) : "文本.txt",
                DefaultExt = "txt",
                RestoreDirectory = false,
                Filter = "文本文件 (*.txt)|*.txt|All Files (*.*)|*.*"
            };

            if(!File.Exists(_textFileName))
            {
                dialog.InitialDirectory = AssemblyUtils.AssemblyDirectory;
            }

            if(dialog.ShowDialog() != DialogResult.Cancel)
            {
                _textFileName = dialog.FileName;
                File.WriteAllText(dialog.FileName,txtContent2.Text,Encoding.UTF8);
            }
        }

        private void menuItemSaveTextListAs_Click(object sender,EventArgs e)
        {
            var dialog = new SaveFileDialog
            {
                OverwritePrompt = true,
                ValidateNames = true,
                Title = "文本列表另存为",
                FileName = File.Exists(_textListFileName) ? Path.GetFileName(_textListFileName) : "文档.xml",
                DefaultExt = "xml",
                RestoreDirectory = false,
                Filter = "XML文档 (*.xml)|*.xml|All Files (*.*)|*.*"
            };

            if(!File.Exists(_textListFileName))
            {
                dialog.InitialDirectory = AssemblyUtils.AssemblyDirectory;
            }

            if(dialog.ShowDialog() != DialogResult.Cancel)
            {
                _textListFileName = dialog.FileName;
                var document = new XDocument();
                document.Add(new XElement("items",gvTextList.Rows.OfType<DataGridViewRow>().Select(x => new XElement("item",((string)x.Cells[0].Value) ?? string.Empty))));
                FileUtils.Save(_textListFileName,document);
            }
        }

        private void menuItemSaveImageAs_Click(object sender,EventArgs e)
        {
            var dialog = new SaveFileDialog
            {
                OverwritePrompt = true,
                ValidateNames = true,
                Title = "图像另存为",
                FileName = File.Exists(_imageFileName) ? Path.GetFileName(_imageFileName) : "图像.bmp",
                DefaultExt = "bmp",
                RestoreDirectory = false,
                Filter = ImageHelper.GetImageFilter()
            };

            if(!File.Exists(_imageFileName))
            {
                dialog.InitialDirectory = AssemblyUtils.AssemblyDirectory;
            }

            if(dialog.ShowDialog() != DialogResult.Cancel)
            {
                _imageFileName = dialog.FileName;
                var fileExtension = Path.GetExtension(dialog.FileName).ToLower();
                var imageFormat = fileExtension == ".bmp" ? ImageFormat.Bmp :
                    fileExtension == ".gif" ? ImageFormat.Gif :
                    fileExtension == ".jpeg" ? ImageFormat.Jpeg :
                    fileExtension == ".png" ? ImageFormat.Png :
                    fileExtension == ".tiff" ? ImageFormat.Tiff : ImageFormat.Wmf;
                pbContent.Image.Save(dialog.FileName,imageFormat);
            }
        }

        private void menuItemSaveEnvironmentAs_Click(object sender,EventArgs e)
        {
            var dialog = new SaveFileDialog
            {
                OverwritePrompt = true,
                ValidateNames = true,
                Title = "环境信息另存为",
                FileName = File.Exists(_environmentFileName) ? Path.GetFileName(_environmentFileName) : "文本.txt",
                DefaultExt = "txt",
                RestoreDirectory = false,
                Filter = "文本文件 (*.txt)|*.txt|All Files (*.*)|*.*"
            };

            if(!File.Exists(_environmentFileName))
            {
                dialog.InitialDirectory = AssemblyUtils.AssemblyDirectory;
            }

            if(dialog.ShowDialog() != DialogResult.Cancel)
            {
                _environmentFileName = dialog.FileName;
                var content = string.Empty;
                if(gvEnvironment.Tag is IDictionary<string,string> variables)
                {
                    const int paddingSize = 25;
                    var builder = new StringBuilder(1024);
                    foreach(var variableKey in variables.Keys)
                    {
                        builder.AppendFormat($"{variableKey.PadRight(paddingSize)}: {variables[variableKey]}{Environment.NewLine}");
                    }
                    content = builder.ToString();
                }
                File.WriteAllText(dialog.FileName,content,Encoding.UTF8);
            }
        }

        private void menuItemExit_Click(object sender,EventArgs e) => Close();

        private void menuItemFont_Click(object sender,EventArgs e)
        {
            var dialog = new FontDialog
            {
                ShowHelp = false,
                ShowColor = false,
                Font = txtContent.Font
            };
            // dialog.Font = txtContent2.Font;
            if(dialog.ShowDialog() != DialogResult.Cancel)
            {
                txtContent.Font = dialog.Font;
                txtContent2.Font = dialog.Font;
            }
        }

        private void menuItemAlwaysOnTop_Click(object sender,EventArgs e)
        {
            TopMost = !TopMost;
            menuItemAlwaysOnTop.Checked = TopMost;
        }

        private void menuItemChecked_Click(object sender,EventArgs e)
        {
            var menuItem = (ToolStripMenuItem)sender;
            menuItem.Checked = !menuItem.Checked;
        }

        private void menuItemShowTextList_Click(object sender,EventArgs e)
        {
            menuItemShowTextList.Checked = !menuItemShowTextList.Checked;
            if(menuItemShowTextList.Checked)
            {
                uiSplitContainer1.Panel2Collapsed = false;
                uiSplitContainer1.Panel2.Show();
            }
            else
            {
                uiSplitContainer1.Panel2Collapsed = true;
                uiSplitContainer1.Panel2.Hide();
            }
        }


        private void btnTarget_MouseDown(object sender,MouseEventArgs e)
        {
            if(!_isButtonTargetMouseDown)
            {
                _isButtonTargetMouseDown = true;
                gvInformation.Rows.Clear();
                gvInformation.Tag = null;
                gvEnvironment.Rows.Clear();
                gvEnvironment.Tag = null;
                gvTextList.Rows.Clear();
                txtContent.Text = string.Empty;
                txtContent2.Text = string.Empty;
                if(!TopMost)
                {
                    SendToBack();
                }
            }
        }


        private void chbRefresh_CheckedChanged(object sender,EventArgs e)
        {
            lock(_lockObject)
            {
                _refreshImage = this.chbRefresh.Checked;
            }
        }

        private void chbCaptureCursor_CheckedChanged(object sender,EventArgs e)
        {
            lock(_lockObject)
            {
                _captureCursor = this.chbCaptureCursor.Checked;
            }
        }


        private void tabContent_SelectedIndexChanged(object sender,EventArgs e)
        {
            lock(_lockObject)
            {
                var tab = (TabControl)sender;
                _imageTab = tab.SelectedTab.Text == "图像";
                EnableImageTabControls();
            }
        }

        public bool PreFilterMessage(ref Message m)
        {
            switch(m.Msg)
            {
                case Constants.WM_LBUTTONUP:
                {
                    if(_isButtonTargetMouseDown)
                    {
                        _isButtonTargetMouseDown = false;
                        User32.SetCursor(Cursors.Default.Handle);
                        if(!TopMost)
                        {
                            BringToFront();
                        }
                    }
                }
                break;

                case Constants.WM_MOUSEMOVE:
                {
                    try
                    {
                        if(_isButtonTargetMouseDown)
                        {
                            User32.SetCursor(Properties.Resources.Target32.Handle);
                            var cursorPosition = Cursor.Position;
                            var element = AutomationElement.FromPoint(new System.Windows.Point(cursorPosition.X,cursorPosition.Y));
                            if(element != null && element.Current.ProcessId != _processId)
                            {
                                var windowHandle = new IntPtr(element.Current.NativeWindowHandle);
                                windowHandle = windowHandle == IntPtr.Zero ? User32.WindowFromPoint(new Point(cursorPosition.X,cursorPosition.Y)) : windowHandle;

                                var previousHandle = IntPtr.Zero;
                                var previousProcessId = 0;
                                lock(_lockObject)
                                {
                                    previousHandle = _windowHandle;
                                    previousProcessId = _windowProcessId;
                                }

                                if(!menuItemAlwaysRefreshTabs.Checked && previousHandle == windowHandle)
                                {
                                    return false;
                                }

                                var process = Process.GetProcessById(element.Current.ProcessId);
                                if(element.Current.IsPassword)
                                {
                                    if(process.ProcessName.ToLower() == "iexplore")
                                    {
                                        if(windowHandle != IntPtr.Zero)
                                        {
                                            var passwords = WindowUtils.GetPasswordsFromHtmlPage(windowHandle);
                                            if(passwords.Any())
                                            {
                                                var text = passwords.Count > 1 ? string.Join(Environment.NewLine,passwords.Select((x,i) => "Password " + (i + 1) + ": " + x)) : passwords[0];
                                                txtContent.Text = text;
                                                AddTextToList(text);
                                                OnContentChanged();
                                            }
                                        }
                                    }
                                    else if(Environment.Is64BitOperatingSystem && !process.HasExited && !process.IsWow64Process())
                                    {
                                        Process.Start(new ProcessStartInfo
                                        {
                                            FileName = _64BitFilePath,
                                            Arguments = string.Format("{0} {1} {2}",Handle.ToInt32(),element.Current.NativeWindowHandle,_messageId)
                                        });
                                    }
                                    else
                                    {
                                        Hook.SetHook(Handle,windowHandle,_messageId);
                                        Hook.QueryPasswordEdit();
                                        Hook.UnsetHook(Handle,windowHandle);
                                    }
                                }
                                else
                                {
                                    var text = element.GetTextFromConsole() ?? element.GetTextFromWindow();
                                    text = text == null ? "" : text.TrimEnd().TrimEnd(Environment.NewLine);
                                    txtContent.Text = text;
                                    AddTextToList(text);

                                    var scale = 1m;
                                    var captureCursor = false;
                                    lock(_lockObject)
                                    {
                                        _windowHandle = windowHandle;
                                        _windowProcessId = element.Current.ProcessId;
                                        scale = _scale;
                                        captureCursor = _captureCursor;
                                    }
                                    if(scale == 1m)
                                    {
                                        var newImage = WindowUtils.CaptureWindow(windowHandle,captureCursor);
                                        FillImage(newImage);
                                    }
                                    else
                                    {
                                        using(var image = WindowUtils.CaptureWindow(windowHandle,captureCursor))
                                        {
                                            var newImage = ImageUtils.ResizeImage(image,(int)(image.Width * scale),(int)(image.Height * scale));
                                            FillImage(newImage);
                                        }
                                    }
                                    var windowInformation = WindowUtils.GetWindowInformation(windowHandle,cursorPosition);
                                    FillInformation(windowInformation);
                                    if(previousProcessId != _windowProcessId)
                                    {
                                        process.TryReadEnvironmentVariables(out var variables);
                                        FillEnvironment(variables);
                                    }
                                    OnContentChanged();
                                }

                            }
                            else
                            {
                                lock(_lockObject)
                                {
                                    _windowHandle = IntPtr.Zero;
                                    _windowProcessId = 0;
                                }
                                FillImage(Properties.Resources.OnePixel);
                                FillInformation(new WindowInformation());
                                FillEnvironment(new Dictionary<string,string>());
                                OnContentChanged();
                            }
                            EnableImageTabControls();
                        }
                    }
                    catch(Exception e)
                    {
                        MessageBox.Show(e.ToString());
                    }
                }
                break;
            }

            return false;
        }

        private void CaptureWindowCallback()
        {
            var scale = 1m;
            var windowHandle = IntPtr.Zero;
            var imageTab = false;
            var isRecording = false;
            var captureCursor = false;


            lock(_lockObject)
            {
                scale = _scale;
                windowHandle = _windowHandle;
                imageTab = _imageTab;
                captureCursor = _captureCursor;
            }

            var newImage = (Bitmap)null;

            if(windowHandle != null && User32.IsWindow(windowHandle))
            {
                if(imageTab || isRecording)
                {
                    if(scale == 1m)
                    {
                        newImage = WindowUtils.CaptureWindow(windowHandle,captureCursor);
                    }
                    else
                    {
                        using(var sourceImage = WindowUtils.CaptureWindow(windowHandle,captureCursor))
                        {
                            newImage = ImageUtils.ResizeImage(sourceImage,(int)(sourceImage.Width * scale),(int)(sourceImage.Height * scale));
                        }
                    }
                }
            }
            else
            {
                newImage = (Bitmap)Properties.Resources.OnePixel.Clone();
            }

            var oldImage = (Bitmap)null;

            lock(_lockObject)
            {
                if(newImage != null)
                {
                    oldImage = _image;
                    _image = newImage;
                }
            }

            oldImage?.Dispose();
        }

        private void UpdatePictureBoxCallback()
        {
            var image = (Bitmap)null;

            lock(_lockObject)
            {
                if(_imageTab && _refreshImage)
                {
                    image = (Bitmap)_image.Clone();
                }
            }

            if(image != null)
            {
                BeginInvoke((MethodInvoker)delegate
                {
                    FillImage(image);
                    OnContentChanged();
                });
            }
        }


        private void InitTimers(int fps)
        {
            var timerInterval = (int)Math.Round(1000m / fps,0,MidpointRounding.AwayFromZero);
            _captureWindowTimer?.Stop();
            _updatePictureBoxTimer?.Stop();
            _captureWindowTimer = new AccurateTimer(CaptureWindowCallback,timerInterval);
            _updatePictureBoxTimer = new AccurateTimer(UpdatePictureBoxCallback,timerInterval);
        }

        private void EnableImageTabControls()
        {
            chbRefresh.Visible = _imageTab;
            chbCaptureCursor.Visible = _imageTab;
        }

        private void OnContentChanged()
        {
            lblTotalChars.Text = "字数: " + txtContent.Text.Length;
            lblTotalLines.Text = "总行数: " + txtContent.Text.Split(new string[] { Environment.NewLine },StringSplitOptions.None).Length;
            lblImageSize.Text = "图像尺寸: " + (pbContent != null && pbContent.Image != null ? $"{pbContent.Image.Width}x{pbContent.Image.Height}" : string.Empty);
            menuItemSaveTextAs.Enabled = txtContent.Text.Length > 0;
            menuItemSaveTextListAs.Enabled = gvTextList.Rows.Count > 0;
            menuItemSaveImageAs.Enabled = pbContent != null && pbContent.Image != null && (pbContent.Image.Width > 1 || pbContent.Image.Height > 1);
            menuItemSaveInformationAs.Enabled = gvInformation.Tag != null && gvInformation.Tag is WindowInformation information && information.WindowDetails.Any() && information.ProcessDetails.Any();
            menuItemSaveEnvironmentAs.Enabled = gvEnvironment.Tag != null && gvEnvironment.Tag is IDictionary<string,string> variables && variables.Any();

        }

        private void FillInformation(WindowInformation windowInformation)
        {
            gvInformation.Rows.Clear();
            gvInformation.Tag = null;

            if(windowInformation.CursorDetails.Keys.Any())
            {
                var indexHeader = gvInformation.Rows.Add();
                var rowHeader = gvInformation.Rows[indexHeader];
                rowHeader.Cells[0].Value = "鼠标信息";
                rowHeader.Cells[0].Style.BackColor = Color.LightGray;
                rowHeader.Cells[1].Style.BackColor = Color.LightGray;
            }

            foreach(var cursorDetailKey in windowInformation.CursorDetails.Keys)
            {
                var index = gvInformation.Rows.Add();
                var row = gvInformation.Rows[index];
                row.Cells[0].Value = cursorDetailKey;
                row.Cells[1].Value = windowInformation.CursorDetails[cursorDetailKey];
            }

            if(windowInformation.WindowDetails.Keys.Any())
            {
                var indexHeader = gvInformation.Rows.Add();
                var rowHeader = gvInformation.Rows[indexHeader];
                rowHeader.Cells[0].Value = "窗口信息";
                rowHeader.Cells[0].Style.BackColor = Color.LightGray;
                rowHeader.Cells[1].Style.BackColor = Color.LightGray;
            }

            foreach(var windowDetailKey in windowInformation.WindowDetails.Keys)
            {
                var index = gvInformation.Rows.Add();
                var row = gvInformation.Rows[index];
                row.Cells[0].Value = windowDetailKey;
                row.Cells[1].Value = windowInformation.WindowDetails[windowDetailKey];
            }

            if(windowInformation.ProcessDetails.Keys.Any())
            {
                var indexHeader = gvInformation.Rows.Add();
                var rowHeader = gvInformation.Rows[indexHeader];
                rowHeader.Cells[0].Value = "进程信息";
                rowHeader.Cells[0].Style.BackColor = Color.LightGray;
                rowHeader.Cells[1].Style.BackColor = Color.LightGray;
            }

            foreach(var processDetailKey in windowInformation.ProcessDetails.Keys)
            {
                var index = gvInformation.Rows.Add();
                var row = gvInformation.Rows[index];
                row.Cells[0].Value = processDetailKey;
                row.Cells[1].Value = windowInformation.ProcessDetails[processDetailKey];
            }

            gvInformation.Tag = windowInformation;
        }

        private void FillEnvironment(IDictionary<string,string> variables)
        {
            gvEnvironment.Rows.Clear();
            gvEnvironment.Tag = null;

            if(variables.Keys.Any())
            {
                var indexHeader = gvEnvironment.Rows.Add();
                var rowHeader = gvEnvironment.Rows[indexHeader];
                rowHeader.Cells[0].Value = "Variable";
                rowHeader.Cells[0].Style.BackColor = Color.LightGray;
                rowHeader.Cells[1].Value = "Value";
                rowHeader.Cells[1].Style.BackColor = Color.LightGray;
            }

            foreach(var variableKey in variables.Keys)
            {
                var index = gvEnvironment.Rows.Add();
                var row = gvEnvironment.Rows[index];
                row.Cells[0].Value = variableKey;
                row.Cells[1].Value = variables[variableKey];
            }

            gvEnvironment.Tag = variables;
        }

        private void FillImage(Image image)
        {
            pbContent.Image?.Dispose();
            pbContent.Image = image;
        }

        private void AddTextToList(string text)
        {
            if(!menuItemShowEmptyItems.Checked && string.IsNullOrEmpty(text))
            {
                return;
            }

            if(menuItemNotRepeated.Checked && _listText == text)
            {
                return;
            }

            _listText = text;

            var index = gvTextList.Rows.Add();
            var row = gvTextList.Rows[index];
            row.Cells[0].Value = text;
            row.Selected = true;
            gvTextList.FirstDisplayedScrollingRowIndex = index;
        }


        private void OnCurrentDomainUnhandledException(object sender,UnhandledExceptionEventArgs e)
        {
            var ex = e.ExceptionObject as Exception;
            ex = ex ?? new Exception("OnCurrentDomainUnhandledException");
            OnThreadException(sender,new ThreadExceptionEventArgs(ex));
        }

        private void OnThreadException(object sender,ThreadExceptionEventArgs e) =>
            MessageBox.Show(e.Exception.Message,AssemblyUtils.AssemblyTitle,MessageBoxButtons.OK,MessageBoxIcon.Error);


        private void btnTarget_MouseUp(object sender,MouseEventArgs e)
        {

        }

        private void gvTextList_CellMouseClick(object sender,DataGridViewCellMouseEventArgs e)
        {
            foreach(DataGridViewRow row in gvTextList.Rows)
            {
                var firstCell = row.Cells[0];
                if(firstCell.Selected)
                {
                    txtContent.Text = ((string)firstCell.Value) ?? string.Empty;
                    OnContentChanged();
                    break;
                }
            }
        }

    }
}